package com.dj.mingkong.portal.biz.service.music.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dj.mingkong.common.exception.ValidateException;
import com.dj.mingkong.common.infrastructure.base.dto.delete.DeleteVo;
import com.dj.mingkong.common.infrastructure.base.dto.page.PageVo;
import com.dj.mingkong.common.infrastructure.eo.database.music.BoxEo;
import com.dj.mingkong.common.infrastructure.eo.database.music.BoxMusicEo;
import com.dj.mingkong.common.infrastructure.eo.database.system.DictionaryEo;
import com.dj.mingkong.common.microservice.UserContext;
import com.dj.mingkong.common.util.AssertUtils;
import com.dj.mingkong.common.util.SmartBeanCopy;
import com.dj.mingkong.portal.biz.constant.Constants;
import com.dj.mingkong.portal.biz.controller.music.vo.request.BoxAddVo;
import com.dj.mingkong.portal.biz.controller.music.vo.request.BoxQueryVo;
import com.dj.mingkong.portal.biz.controller.music.vo.request.BoxUpdateVo;
import com.dj.mingkong.portal.biz.controller.music.vo.response.BoxDetailVo;
import com.dj.mingkong.portal.biz.controller.music.vo.response.BoxVo;
import com.dj.mingkong.portal.biz.enums.BoxTypeEnum;
import com.dj.mingkong.portal.biz.repository.database.music.*;
import com.dj.mingkong.portal.biz.repository.database.system.DictionaryRepository;
import com.dj.mingkong.portal.biz.service.music.BoxService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

/**
 * 音乐盒服务实现
 *
 * @author zenglonghui
 * @date: 2022/8/31 22:06
 */
@Slf4j
@Service("boxService")
public class BoxServiceImpl implements BoxService {
    @Resource
    private BoxRepository boxRepository;
    @Resource
    private DictionaryRepository dictionaryRepository;
    @Resource
    private BoxMusicRepository boxMusicRepository;
    @Resource
    private MusicRepository musicRepository;
    @Resource
    private BoxLikeRepository boxLikeRepository;
    @Resource
    private BoxVisitRepository boxVisitRepository;
    @Resource
    private BoxCollectRepository boxCollectRepository;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(BoxAddVo addVo) {
        if (boxRepository.existByNameAndUserId(addVo.getName(), UserContext.getUserId())) {
            throw new ValidateException("BoxName already exist!");
        }
        boxRepository.save(buildBoxEo(addVo));
    }

    private BoxEo buildBoxEo(BoxAddVo addVo) {
        return BoxEo.builder()
                .name(addVo.getName())
                .type(BoxTypeEnum.CREATE.getType())
                .userId(UserContext.getUserId())
                .cover(StringUtils.isNotBlank(addVo.getCover()) ? addVo.getCover() : "")
                .description(StringUtils.isNotBlank(addVo.getDescription()) ? addVo.getDescription() : "")
                .build();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateById(BoxUpdateVo updateVo) {
        final BoxEo boxEo = boxRepository.getById(updateVo.getId());
        AssertUtils.isNotNull(boxEo, "Id invalid!");
        if (BoxTypeEnum.DEFAULT.equalsType(boxEo.getType())) {
            throw new ValidateException("Not allow update!");
        }
        if (!boxEo.getUserId().equals(UserContext.getUserId())) {
            throw new ValidateException("Modify without permission!");
        }
        if (!boxEo.getName().equals(updateVo.getName())
                && boxRepository.existByNameAndUserId(updateVo.getName(), boxEo.getUserId())) {
            throw new ValidateException("BoxName already exist!");
        }
        final BoxEo eo = SmartBeanCopy.copy(updateVo, BoxEo.class);
        boxRepository.updateById(eo);
    }

    @Override
    public List<BoxDetailVo> listMyBox(Long userId) {
        final List<BoxEo> boxEos = boxRepository.listByUserId(userId);
        final List<BoxDetailVo> boxDetailVos = SmartBeanCopy.copy(boxEos, BoxDetailVo.class);
        boxDetailVos.forEach(this::buildBoxCover);
        return boxDetailVos;
    }

    @Override
    public PageVo<BoxVo> pageByVo(BoxQueryVo queryVo) {
        final Page<BoxEo> boxEoPage = boxRepository.listPageByVo(queryVo);
        final PageVo<BoxVo> boxVoPage = SmartBeanCopy.copyPageVo(boxEoPage, BoxVo.class);
        boxVoPage.getRecords().forEach(this::buildBoxCover);
        return boxVoPage;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteById(DeleteVo deleteVo) {
        final BoxEo boxEo = boxRepository.getById(deleteVo.getId());
        AssertUtils.isNotNull(boxEo, "Id invalid!");
        if (!UserContext.getUserId().equals(boxEo.getUserId())) {
            throw new ValidateException("No permission!");
        }
        if (BoxTypeEnum.DEFAULT.equalsType(boxEo.getType())) {
            throw new ValidateException("Not allow delete!");
        }
        boxRepository.deleteById(deleteVo.getId());
        boxCollectRepository.deleteByBoxId(deleteVo.getId());
        boxLikeRepository.deleteByBoxId(deleteVo.getId());
        boxMusicRepository.deleteByBoxId(deleteVo.getId());
        boxVisitRepository.deleteByBoxId(deleteVo.getId());
    }

    private void buildBoxCover(BoxDetailVo boxVo) {
        if (StringUtils.isBlank(boxVo.getCover())) {
            if (BoxTypeEnum.DEFAULT.equalsType(boxVo.getType())) {
                final Optional<DictionaryEo> eoOptional = dictionaryRepository
                        .oneOptByFullKey(Constants.DEFAULT_BOX_COVER_DICT_FULL_KEY);
                boxVo.setCover(eoOptional.isEmpty() ? "" : eoOptional.get().getDictValue());
            } else {
                final List<BoxMusicEo> boxMusicEos = boxMusicRepository.listByBoxId(boxVo.getId());
                if (CollectionUtils.isNotEmpty(boxMusicEos)) {
                    boxVo.setCover(musicRepository.getById(boxMusicEos.get(0).getMusicId()).getCover());
                } else {
                    final Optional<DictionaryEo> eoOptional = dictionaryRepository
                            .oneOptByFullKey(Constants.DEFAULT_BOX_COVER_DICT_FULL_KEY);
                    boxVo.setCover(eoOptional.isEmpty() ? "" : eoOptional.get().getDictValue());
                }
            }
        }
    }

    private void buildBoxCover(BoxVo boxVo) {
        if (StringUtils.isBlank(boxVo.getCover())) {
            if (BoxTypeEnum.DEFAULT.equalsType(boxVo.getType())) {
                final Optional<DictionaryEo> eoOptional = dictionaryRepository
                        .oneOptByFullKey(Constants.DEFAULT_BOX_COVER_DICT_FULL_KEY);
                boxVo.setCover(eoOptional.isEmpty() ? "" : eoOptional.get().getDictValue());
            } else {
                final List<BoxMusicEo> boxMusicEos = boxMusicRepository.listByBoxId(boxVo.getId());
                if (CollectionUtils.isNotEmpty(boxMusicEos)) {
                    boxVo.setCover(musicRepository.getById(boxMusicEos.get(0).getMusicId()).getCover());
                } else {
                    final Optional<DictionaryEo> eoOptional = dictionaryRepository
                            .oneOptByFullKey(Constants.DEFAULT_BOX_COVER_DICT_FULL_KEY);
                    boxVo.setCover(eoOptional.isEmpty() ? "" : eoOptional.get().getDictValue());
                }
            }
        }
    }

   /* @Override
    public SearchHits<BoxEsEo> searchLikeName(String name) {
        //设置查询分页
        final PageRequest pageRequest = PageRequest.of(0, CommonConstants.DEFAULT_PAGE_SIZE, WrapperUtil.buildEsSort(""));
        //构建查询条件
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.termQuery("status", StatusEnum.VALID.getIntVal()))
                .must(QueryBuilders.termQuery("type", BoxTypeEnum.CREATE.getType()))
                .must(QueryBuilders.fuzzyQuery("name", name).fuzziness(Fuzziness.ONE));
        // 构建查询
        final NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(pageRequest)
                .build();
        //执行查询
        return elasticsearchRestTemplate.search(nativeSearchQuery, BoxEsEo.class);
    }

    @Override
    public SearchHits<BoxEsEo> searchByVo(BoxQueryEsVo queryVo) {
        //设置查询分页
        final PageRequest pageRequest = PageRequest.of(queryVo.getPage() - 1, queryVo.getPageSize(), WrapperUtil.buildEsSort(queryVo.getSort()));
        //构建查询条件
        final BoolQueryBuilder boolQueryBuilder = buildBoolQueryBuilder(queryVo);
        //设置高亮字段
        final HighlightBuilder highlightBuilder = buildHighlightBuilder();
        // 构建查询
        final NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withHighlightBuilder(highlightBuilder)
                .withPageable(pageRequest)
                .build();
        //执行查询
        return elasticsearchRestTemplate.search(nativeSearchQuery, BoxEsEo.class);
    }

    private HighlightBuilder buildHighlightBuilder() {
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //设置标签前缀
        highlightBuilder.preTags("<font color='#00F7DE'>");
        //设置标签后缀
        highlightBuilder.postTags("</font>");
        //设置高亮字段
        highlightBuilder.field("name");
        return highlightBuilder;
    }

    private BoolQueryBuilder buildBoolQueryBuilder(BoxQueryEsVo queryVo) {
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.termQuery("status", StatusEnum.VALID.getIntVal()))
                .must(QueryBuilders.termQuery("type", BoxTypeEnum.CREATE.getType()))
                .must(QueryBuilders.fuzzyQuery("name", queryVo.getName()).fuzziness(Fuzziness.ONE));
        return boolQueryBuilder;
    }*/
}
